<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2019/1/6
 * Time: 20:29
 */

namespace App\Services;


use Illuminate\Support\Str;
use Overtrue\EasySms\EasySms;

class VerificationCode
{
    const USER_REGISTER = 1;
    const USER_LOGIN = 2;
    const PASSWORD_FORGET = 3;
    const PASSWORD_RESET = 4;

    const TEMPLATE = [
        self::USER_REGISTER => "SMS_152460548",
        self::USER_LOGIN => "SMS_152460548",
        self::PASSWORD_FORGET => "SMS_152460548",
        self::PASSWORD_RESET => "SMS_152460548",
    ];

    const TYPE_DESCRIPTION = [
        self::USER_REGISTER => "用户注册",
        self::USER_LOGIN => "用户登录",
        self::PASSWORD_FORGET => "找回密码",
        self::PASSWORD_RESET => "修改密码",
    ];

    private $sender;

    public function __construct(EasySms $sms)
    {
        $this->sender = $sms;
    }

    public function send($mobile, $type)
    {
        $template = self::TEMPLATE[$type];
        if (app()->environment('production')) {
            try {
                $this->sender->send($mobile, [
                    'template' => $template,
                    'data' => [
                        'code' => $this->code($mobile, $type),
                    ],
                ]);
            } catch (\Overtrue\EasySms\Exceptions\NoGatewayAvailableException $exception) {
                $message = $exception->getException('aliyun')->getMessage();
                logger("SMS", [
                    "errorMsg" => $message,
                    "mobile" => $mobile,
                    "type" => self::TYPE_DESCRIPTION[$type],
                    "template" => $template
                ]);
                return false;
            }
        } else {
            $this->code($mobile, $type, "000000");
        }

        return true;
    }

    private function code($mobile, $type, $hasCode = null)
    {
        $cacheKey = self::getCacheKey($mobile, $type);
        $data = cache($cacheKey);

        if (!$data) {
            $code = $hasCode ?: rand(100000, 999999);
            $data = [
                "code" => (string)$code,
                "mobile" => $mobile,
                "type" => $type,
            ];
            cache()->put($cacheKey, $data, 5);
        }
        return $data["code"];
    }

    private static function getCacheKey($mobile, $type)
    {
        return md5($mobile . $type);
    }

    public static function verify($params)
    {
        $cacheKey = self::getCacheKey($params["mobile"], $params["type"]);
        $data = cache($cacheKey);
        if (!$data) {
            return [
                "code" => 401,
                "msg" => "验证码已过期"
            ];
        }
        if (!hash_equals($data["code"], $params["code"])) {
            return [
                "code" => 422,
                "msg" => "验证码错误",
            ];
        }
        cache()->forget($cacheKey);
        return false;
    }
}